home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / analogjoystick / joydriv.c < prev    next >
C/C++ Source or Header  |  1980-01-07  |  10KB  |  350 lines

  1.  
  2.  
  3.  
  4. /*********************************************************/
  5. /*                                                       */
  6. /* Copyright (c) 1989, David Kinzer, All Rights Reserved */
  7. /*                                                       */
  8. /* Permission hereby granted to redistribute this        */
  9. /* program in unmodified form in a not for profit manner.*/
  10. /*                                                       */
  11. /* Permission hereby granted to use this software freely */
  12. /* in programs, commercial or not.                       */
  13. /*                                                       */
  14. /*********************************************************/
  15. /*                                                       */
  16. /* JoyDriv.c                                             */
  17. /*                                                       */
  18. /* Analog joystick interface routines                    */
  19. /*                                                       */
  20. /* This file contains the routines needed to interface   */
  21. /* to an analog joystick.  The routines supplied will    */
  22. /* open, read, and close an analog joystick port.        */
  23. /* Note that in order to use joyport 0 (left mouse port) */
  24. /* the intuition interface will have to be turned off.   */
  25. /*                                                       */
  26. /*********************************************************/
  27.  
  28. #include "exec/types.h"
  29. #include "exec/memory.h"
  30. #include "exec/interrupts.h"
  31. #include "hardware/custom.h"
  32. #include "hardware/intbits.h"
  33.  
  34. #include "ajoystick.h"
  35.  
  36. #define POTBITS0        0x0F01
  37. #define POTBITS1        0xF001
  38. #define INPUT0          0x0000
  39. #define INPUT1          0x0000
  40. #define INMASK0         0x0A00
  41. #define INMASK1         0xA000
  42.  
  43.  
  44.  
  45.  
  46. struct joydata {
  47.    struct {
  48.       unsigned short x;
  49.       unsigned short y;
  50.       char b1;
  51.       char b2;
  52.       char b3;
  53.       char b4;
  54.       char eb1;
  55.       char eb2;
  56.       char eb3;
  57.       char eb4;
  58.    } unit0,unit1;
  59.    APTR pgbase;
  60.    long unitflags;
  61. };
  62.  
  63.  
  64.  
  65.  
  66. APTR PotgoBase = 0;               /* Library base        */
  67. long gotpotgo = 0;                /* Potgo register bits */
  68.                                   /*  we are using       */
  69. struct joydata *JoyData = NULL;   /* Pointer to data     */
  70.                                   /*  passing area       */
  71. struct Interrupt *VBRData = NULL; /* Pointer to VERTB    */
  72.                                   /*  interrupt node     */
  73. extern VOID vbserver();
  74.  
  75.  
  76. /* Open Analog Joystick Routine */
  77.  
  78. struct joydata *OpenAJoystick(units)
  79. long units;
  80. {
  81. long wantpotgo, AllocPotBits();
  82. long inputbits, inputmask;
  83. APTR OpenResource(), AllocMem();
  84.  
  85.  
  86.    /* reject open if already opened. */
  87.  
  88.    if (JoyData) {
  89.       return NULL;
  90.    }
  91.  
  92.    /* Open potgo resource.  The resource controls        */
  93.    /* allocation and writing of the potgo register.      */
  94.    /* Note: There is no corresponding CloseResource call */
  95.    /*       in the Amiga.                                */
  96.  
  97.    PotgoBase = OpenResource((STRPTR)"potgo.resource");
  98.    if (!PotgoBase) {
  99.       return NULL;    /* Return error if potgo.resource */
  100.                       /* is not available.              */
  101.    }
  102.  
  103.    /* figure out which bits we need */
  104.  
  105.    wantpotgo = 0;
  106.    inputbits = 0;
  107.    inputmask = 0;
  108.  
  109.    if (units & AJOYUNIT0) {
  110.       wantpotgo |= POTBITS0;
  111.       inputbits |= INPUT0;
  112.       inputmask |= INMASK0;
  113.    }
  114.  
  115.    if (units & AJOYUNIT1) {
  116.       wantpotgo |= POTBITS1;
  117.       inputbits |= INPUT1;
  118.       inputmask |= INMASK1;
  119.    }
  120.  
  121.    /* Do we want anything?  If not, return error, since */
  122.    /* there is probably an error in the call.           */
  123.  
  124.    if (!wantpotgo) {
  125.       return NULL;
  126.    }
  127.  
  128.  
  129.    /* Allocate the bits that we need from the potgo  */
  130.    /* resource.                                      */
  131.  
  132.    gotpotgo = AllocPotBits(wantpotgo);
  133.  
  134.    /* See if we got what we needed. If not, return error */
  135.  
  136.    if (wantpotgo != gotpotgo) {
  137.       FreePotBits(gotpotgo); /* give back allocated bits */
  138.       return NULL;
  139.    }
  140.  
  141.  
  142.    /* Since we don't know what the hardware was set to   */
  143.    /* before we got it, we shall set the analog joystick */
  144.    /* bits to inputs like we want.                       */
  145.  
  146.    WritePotgo(inputbits,inputmask);
  147.  
  148.    /* Now that we have the hardware, we shall set up our */
  149.    /* VERTB (vertical blanking) interrupt server routine.*/
  150.    /* We get some Public memory for a shared data area   */
  151.    /* between the server and the ReadAJoystick routine.  */
  152.    /* Then we set up an interrupt structure which allows */
  153.    /* our server to become a part of the Amiga operating */
  154.    /* system.                                            */
  155.  
  156.    JoyData = (struct joydata *)AllocMem((long)sizeof
  157.                (struct joydata),MEMF_PUBLIC);
  158.    if (!JoyData) {       /* error if we can't get memory */
  159.       FreePotBits(gotpotgo); /* give back allocated bits */
  160.       return NULL;
  161.    }
  162.  
  163.    JoyData->pgbase = PotgoBase;     /* send potgobase to */
  164.                                     /*  vertb server     */
  165.    JoyData->unitflags = units;      /* send units to     */
  166.                                     /*  vertb server     */
  167.  
  168.    JoyData->unit0.x = 0x8000;       /* fill in some      */
  169.    JoyData->unit0.y = 0x8000;       /*  dummy values     */
  170.    JoyData->unit0.b1 = 0;
  171.    JoyData->unit0.b2 = 0;
  172.    JoyData->unit0.b3 = 0;
  173.    JoyData->unit0.b4 = 0;
  174.    JoyData->unit0.eb1 = 0;
  175.    JoyData->unit0.eb2 = 0;
  176.    JoyData->unit0.eb3 = 0;
  177.    JoyData->unit0.eb4 = 0;
  178.    JoyData->unit1.x = 0x8000;       
  179.    JoyData->unit1.y = 0x8000;
  180.    JoyData->unit1.b1 = 0;
  181.    JoyData->unit1.b2 = 0;
  182.    JoyData->unit1.b3 = 0;
  183.    JoyData->unit1.b4 = 0;
  184.    JoyData->unit1.eb1 = 0;
  185.    JoyData->unit1.eb2 = 0;
  186.    JoyData->unit1.eb3 = 0;
  187.    JoyData->unit1.eb4 = 0;
  188.  
  189.    VBRData = (struct Interrupt *)AllocMem((long)sizeof
  190.                 (struct Interrupt),MEMF_PUBLIC);
  191.    if (!VBRData) {       /* error if we can't get memory */
  192.       /* give back memory and allocated potgo bits */
  193.       FreeMem(JoyData,(long)sizeof(struct joydata));
  194.       FreePotBits(gotpotgo);        
  195.       return NULL;
  196.    }
  197.  
  198.  
  199.    /* Fill in the blanks of the Interrupt structure */
  200.  
  201.    VBRData->is_Node.ln_Type = NT_INTERRUPT;
  202.    VBRData->is_Node.ln_Pri = 10;
  203.    VBRData->is_Node.ln_Name = "VERTB for Analog Joystick";
  204.    VBRData->is_Data = (APTR)JoyData;
  205.    VBRData->is_Code = vbserver;
  206.  
  207.    /* And, finally, add interrupt routine to Operating  */
  208.    /* System.                                           */
  209.  
  210.    AddIntServer(INTB_VERTB,VBRData);
  211.  
  212.    /* Return pointer to data, in case user wants to go  */
  213.    /* directly to the data structures.                  */
  214.  
  215.    return JoyData;
  216.  
  217. }
  218.  
  219.  
  220. /* Close Analog Joystick routine.                       */
  221. /* Note: Since the Units are closely intertwined, I     */
  222. /*       decided to close all open units with one call. */
  223. /*       (since you had to open them with one call      */
  224. /*       anyway).                                       */
  225.  
  226. long CloseAJoystick()
  227. {
  228.  
  229.    /* Are we actually open? Error if not */
  230.  
  231.    if (!JoyData) {
  232.       return 0;
  233.    }
  234.  
  235.    /* Shut off VERTB routine */
  236.  
  237.    RemIntServer(INTB_VERTB,VBRData);
  238.  
  239.    /* Free up memory */
  240.  
  241.    FreeMem(JoyData,(long)sizeof(struct joydata));  
  242.    FreeMem(VBRData,(long)sizeof(struct Interrupt)); 
  243.  
  244.    /* Give back allocated potgo bits */
  245.  
  246.    FreePotBits(gotpotgo);
  247.  
  248.    /* Set Flag so we don't read bad data */
  249.  
  250.    JoyData = NULL;
  251.  
  252.    /* return success */
  253.  
  254.    return 1;
  255. }
  256.  
  257.  
  258. /* Joystick Read routine                                 */
  259. /* Note: Reads values left by last VERTB interrupt.      */
  260. /* Note: Data is stale until first interrupt comes along.*/
  261. /* Note: Only one Unit can be read at a time.            */
  262.  
  263. struct AJoyData *ReadAJoystick(unit,UserDataPtr)
  264. long unit;
  265. struct AJoyData *UserDataPtr;
  266. {
  267.  
  268.    /* Are we open? Error if not. */
  269.  
  270.    if (!JoyData) {
  271.       return NULL;
  272.    }
  273.  
  274.    /* Is this unit open? Error if not */
  275.  
  276.    if (!(JoyData->unitflags & unit)) {
  277.       return NULL;
  278.    }
  279.  
  280.    /* Get data for unit and place in requestor's data    */
  281.    /* structure. (Should be public memory.)              */
  282.  
  283.    if (unit == AJOYUNIT0) {
  284.  
  285.       UserDataPtr->x = JoyData->unit0.x;
  286.       UserDataPtr->y = JoyData->unit0.y;
  287.  
  288.       if (JoyData->unitflags & U0B1SINGLE) {
  289.          UserDataPtr->button1 = JoyData->unit0.eb1;
  290.          JoyData->unit0.eb1 = 0;
  291.       } else 
  292.          UserDataPtr->button1 = JoyData->unit0.b1;
  293.  
  294.       if (JoyData->unitflags & U0B2SINGLE) {
  295.          UserDataPtr->button2 = JoyData->unit0.eb2;
  296.          JoyData->unit0.eb2 = 0;
  297.       } else 
  298.          UserDataPtr->button2 = JoyData->unit0.b2;
  299.  
  300.       if (JoyData->unitflags & U0B3SINGLE) {
  301.          UserDataPtr->button3 = JoyData->unit0.eb3;
  302.          JoyData->unit0.eb3 = 0;
  303.       } else 
  304.          UserDataPtr->button3 = JoyData->unit0.b3;
  305.  
  306.       if (JoyData->unitflags & U0B4SINGLE) {
  307.          UserDataPtr->button4 = JoyData->unit0.eb4;
  308.          JoyData->unit0.eb4 = 0;
  309.       } else 
  310.          UserDataPtr->button4 = JoyData->unit0.b4;
  311.  
  312.    } else if (unit == AJOYUNIT1) {
  313.  
  314.       UserDataPtr->x = JoyData->unit1.x;
  315.       UserDataPtr->y = JoyData->unit1.y;
  316.  
  317.       if (JoyData->unitflags & U1B1SINGLE) {
  318.          UserDataPtr->button1 = JoyData->unit1.eb1;
  319.          JoyData->unit1.eb1 = 0;
  320.       } else 
  321.          UserDataPtr->button1 = JoyData->unit1.b1;
  322.  
  323.       if (JoyData->unitflags & U1B2SINGLE) {
  324.          UserDataPtr->button2 = JoyData->unit1.eb2;
  325.          JoyData->unit1.eb2 = 0;
  326.       } else 
  327.          UserDataPtr->button2 = JoyData->unit1.b2;
  328.  
  329.       if (JoyData->unitflags & U1B3SINGLE) {
  330.          UserDataPtr->button3 = JoyData->unit1.eb3;
  331.          JoyData->unit1.eb3 = 0;
  332.       } else 
  333.          UserDataPtr->button3 = JoyData->unit1.b3;
  334.  
  335.       if (JoyData->unitflags & U1B4SINGLE) {
  336.          UserDataPtr->button4 = JoyData->unit1.eb4;
  337.          JoyData->unit1.eb4 = 0;
  338.       } else 
  339.          UserDataPtr->button4 = JoyData->unit1.b4;
  340.  
  341.    } else return NULL;  /* Error, not a recognised unit */
  342.  
  343.    /* return success */
  344.  
  345.    return UserDataPtr;
  346.  
  347. }
  348.  
  349. /* End: JoyDriv.c */
  350.